(function($) {

	function RouterHistory() {

		var caches = [];

		var index = -1;

		var historyChangedListeners = [];

		var init = function() {
			if(sessionStorage) {
				var sessionCaches = sessionStorage.caches;
				if(sessionCaches) {
					index = Number(sessionStorage.cachesIndex);
					sessionCaches = JSON.parse(sessionCaches);
					caches = sessionCaches.caches;
				}
			}
		}

		var historyChanged = function(title, router, data, dir) {
			$(historyChangedListeners).each(function() {
				this.call(history, title, router, data, dir);
			});
		};
		
		this.push = function(title, router, data) {
			if(index > -1 && index < caches.length - 1) {
				while(index < caches.length - 1) {
					caches.pop();
				}
			}
			var url = window.location.href;
			var uIndex = url.indexOf("#");
			if(uIndex > -1) {
				url = url.substring(0, uIndex);
			}
			url += router.indexOf("#") == 0 ? router : ("#" + router);
			index = caches.length;
			var state = {
				index : index,
				title : title,
				router : router
			};
			caches.push(data ? data : {});
			if(sessionStorage) {
				sessionStorage.cachesIndex = index;
				sessionStorage.caches = JSON.stringify({caches:caches});
			}
			window.history.pushState(state, title, url);
		}

		this.reload = function() {
			popstate();
		}

		this.addHistoryChangedListener = function(historyChangedListener) {
			if(typeof(historyChangedListener) == "function") {
				historyChangedListeners.push(historyChangedListener);
			}
		}

		function popstate() {
			if (history.state){
				var state = history.state;
				var dir = state.index < index ? -1 : (state.index > index ? 1 : 0);
				index = state.index;
				if(index < caches.length && state.router && state.title) {
					historyChanged(state.title, state.router, caches[index], dir);
				}
			}
		}

		window.addEventListener('popstate', function(){
			popstate();
		}, false);

		init();
	}

	$.extend({
		history : function(historyChangedListener) {
			var his = $(document).data("_router_history");
			if(!his) {
				his = new RouterHistory();
				$(document).data("_router_history", his);
			}
			if(historyChangedListener) {
				his.addHistoryChangedListener(historyChangedListener);
			}
			return his;
		}
	});



})(jQuery);
